package com.ershijin.clientserver.config;

import com.ershijin.common.CustomizerGrantedAuthority;
import com.ershijin.common.CustomizerOAuth2AuthenticatedPrincipal;
import net.minidev.json.JSONArray;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.oauth2.server.resource.introspection.NimbusOpaqueTokenIntrospector;
import org.springframework.stereotype.Component;

import java.util.stream.Collectors;

/**
 * 参考 DefaultOAuth2UserService
 */
@Component
public class CustomizerOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        String userInfoUri = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri();
        String clientId = userRequest.getClientRegistration().getClientId();
        String clientSecret = userRequest.getClientRegistration().getClientSecret();

        NimbusOpaqueTokenIntrospector tokenIntrospector = new NimbusOpaqueTokenIntrospector(userInfoUri, clientId, clientSecret);
        OAuth2AuthenticatedPrincipal introspect = tokenIntrospector.introspect(userRequest.getAccessToken().getTokenValue());

        CustomizerOAuth2AuthenticatedPrincipal customizerOAuth2AuthenticatedPrincipal = new CustomizerOAuth2AuthenticatedPrincipal();
        customizerOAuth2AuthenticatedPrincipal.setName(introspect.getName());
        customizerOAuth2AuthenticatedPrincipal.setAttributes(introspect.getAttributes());
        customizerOAuth2AuthenticatedPrincipal.setAuthorities(((JSONArray) introspect.getAttribute("authorities")).stream().map(o -> new CustomizerGrantedAuthority(o.toString())).collect(Collectors.toSet()));

        return customizerOAuth2AuthenticatedPrincipal;
    }
}
